import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:flutter_lui/flutter_lui.dart';
import 'package:flutter_lui/src/l_style.dart';

/// children 排列方向
enum BoxDirections { vertical, horizontal }

/// 盒子容器
class LBox extends StatelessWidget {
  /// 宽度
  final double? width;

  /// 高度
  final double? height;

  /// 弹性盒子
  final int? flex;

  /// 背景颜色
  final Color? backgroundColor;

  /// 背景图片
  final String? backgroundImage;

  /// 背景图片对齐方式
  final Alignment? backgroundImageAlignment;

  /// 背景图片缩放
  final BoxFit? backgroundImageFit;

  /// 背景图片透明度
  final double? backgroundImageOpacity;

  /// 背景图片是否反色
  final bool? backgroundImageInvertColors;

  /// 毛玻璃特效 范围在 0 - 10, \
  /// 需要放置于图片上方才能显示效果, \
  /// 可以外层再包一层LBox,给外层LBox设置背景图,内层设置模糊程度
  final double? glassFilter;

  /// 字体颜色
  final Color? color;

  /// 字体大小
  final double? fontSize;

  /// 文本对齐方式
  final TextAlign? textAlign;

  /// 文本删除线
  final bool textDeleteline;

  /// 文本下划线
  final bool textUnderline;

  /// 字体粗细
  final FontWeight? fontWeight;

  /// 圆角
  /// - [1]=>all
  /// - [1,1]=>[左上右下，右上左下]
  /// - [1,1,1]=> [左上，右上左下，右下]
  /// - [1,1,1,1]=> [左上，右上，右下，左下]
  final List<double> borderRadius;

  /// 左上圆角
  final double? borderRadiusTopLeft;

  /// 右上圆角
  final double? borderRadiusTopRight;

  /// 左下圆角
  final double? borderRadiusBottomLeft;

  /// 右下圆角
  final double? borderRadiusBottomRight;

  /// 边框设置 配合border使用
  final BorderSide? borderSide;

  /// 是否显示边框 配合borderSide使用
  /// - [true]=>all
  /// - [true,true]=>[上下，右左]
  /// - [true,true,true]=> [上，右左，下]
  /// - [true,true,true,true]=> [上，右，下，左]
  final List<bool> border;

  /// 左边框 优先级高于border
  final BorderSide? borderLeft;

  /// 右边框 优先级高于border
  final BorderSide? borderRight;

  /// 上边框 优先级高于border
  final BorderSide? borderTop;

  /// 下边框 优先级高于border
  final BorderSide? borderBottom;

  /// 子控件  Widget 类型直接显示，非Widget类型转成字符串后使用Text显示 不可和children同时使用
  final dynamic child;

  /// 子控件组 每一项子控件 Widget 类型直接显示，非Widget类型转成字符串后使用Text显示 不可和child同时使用
  final List<dynamic>? children;

  /// 子控件排列方向
  final Alignment? alignment;

  /// 主轴对齐方式
  final MainAxisAlignment mainAxisAlignment;

  /// 交叉轴对齐方式
  final CrossAxisAlignment crossAxisAlignment;

  /// 主轴大小
  final MainAxisSize mainAxisSize;

  /// 子控件排列方向
  final BoxDirections? direction;

  /// 内边距
  /// - [1]=>all
  /// - [1,1]=>[上下，右左]
  /// - [1,1,1]=> [上，右左，下]
  /// - [1,1,1,1]=> [上，右，下，左]
  final List<double> padding;

  /// 左内边距
  final double? paddingLeft;

  /// 右内边距
  final double? paddingRight;

  /// 上内边距
  final double? paddingTop;

  /// 下内边距
  final double? paddingBottom;

  /// 上下内边距
  final double? paddingVertical;

  /// 左右内边距
  final double? paddingHorizontal;

  /// 外边距
  /// - [1]=>all
  /// - [1,1]=>[上下，右左]
  /// - [1,1,1]=> [上，右左，下]
  /// - [1,1,1,1]=> [上，右，下，左]
  final List<double> margin;

  /// 左外边距
  final double? marginLeft;

  /// 右外边距
  final double? marginRight;

  /// 上外边距
  final double? marginTop;

  /// 下外边距
  final double? marginBottom;

  /// 上下外边距
  final double? marginVertical;

  /// 左右外边距
  final double? marginHorizontal;

  /// 阴影
  final List<BoxShadow>? boxShadow;

  /// 文字阴影
  final List<Shadow>? textShadow;

  /// 渐变
  final Gradient? gradient;

  /// 点击事件
  final void Function()? onTap;

  /// 拖拽开始 按下事件
  final void Function(DragDownDetails)? onPanDown;

  /// 拖拽中事件
  final void Function(DragUpdateDetails)? onPanUpdate;

  /// 拖拽结束 释放事件
  final void Function(DragEndDetails)? onPanEnd;
  const LBox(
      {this.alignment,
      this.backgroundColor,
      this.backgroundImage,
      this.backgroundImageFit,
      this.backgroundImageOpacity,
      this.backgroundImageInvertColors,
      this.backgroundImageAlignment,
      this.glassFilter,
      this.child,
      this.children,
      this.color,
      this.direction,
      this.fontSize,
      this.height,
      this.textAlign,
      this.textShadow,
      this.margin = const [0],
      this.marginBottom,
      this.marginHorizontal,
      this.marginLeft,
      this.marginRight,
      this.marginTop,
      this.marginVertical,
      this.onTap,
      this.onPanDown,
      this.onPanUpdate,
      this.onPanEnd,
      this.padding = const [0],
      this.paddingBottom,
      this.paddingHorizontal,
      this.paddingLeft,
      this.paddingRight,
      this.paddingTop,
      this.paddingVertical,
      this.width,
      this.fontWeight,
      this.textDeleteline = false,
      this.textUnderline = false,
      this.mainAxisAlignment = MainAxisAlignment.start,
      this.crossAxisAlignment = CrossAxisAlignment.center,
      this.mainAxisSize = MainAxisSize.max,
      this.borderSide,
      this.border = const [false],
      this.borderBottom,
      this.borderLeft,
      this.borderRight,
      this.borderTop,
      this.borderRadius = const [0],
      this.borderRadiusBottomLeft,
      this.borderRadiusBottomRight,
      this.borderRadiusTopLeft,
      this.borderRadiusTopRight,
      this.boxShadow,
      this.gradient,
      this.flex,
      Key? key})
      : assert(!(child != null && children != null), 'child和children只能有一个'),
        super(key: key);
  Widget? createChild(c) {
    Widget? showChild;
    if (c != null) {
      if (c is Widget) {
        showChild = c;
      } else {
        showChild = LText(
          c.toString(),
          align: textAlign ?? TextAlign.start,
          shadow: textShadow,
          color: color,
          fontSize: fontSize,
          fontWeight: fontWeight,
          underline: textUnderline,
          deleteline: textDeleteline,
        );
      }
    }
    return showChild;
  }

  @override
  Widget build(BuildContext context) {
    Widget? showChild;
    if (child != null) {
      showChild = createChild(child);
    } else if (children?.isNotEmpty == true) {
      List<Widget> showChildren = [];
      for (var c in children!) {
        var sc = createChild(c);
        if (sc != null) showChildren.add(sc);
      }
      if (direction == BoxDirections.horizontal) {
        showChild = Row(
            mainAxisAlignment: mainAxisAlignment,
            crossAxisAlignment: crossAxisAlignment,
            mainAxisSize: mainAxisSize,
            children: showChildren);
      } else {
        showChild = Column(
            mainAxisAlignment: mainAxisAlignment,
            crossAxisAlignment: crossAxisAlignment,
            mainAxisSize: mainAxisSize,
            children: showChildren);
      }
    }
    var showBorderSide = borderSide ??
        BorderSide(width: lrpx(1), color: LUI.instance.borderColor);
    var showBorder = findTRBL(border);
    var hasBorder = borderTop != null ||
        borderRight != null ||
        borderBottom != null ||
        borderLeft != null ||
        showBorder.contains(true);
    var hasBorderRadius = borderRadiusTopLeft ??
        findTRBL(borderRadius)[0] ??
        borderRadiusTopRight ??
        findTRBL(borderRadius)[1] ??
        borderRadiusBottomRight ??
        findTRBL(borderRadius)[2] ??
        borderRadiusBottomLeft ??
        findTRBL(borderRadius)[3] ??
        0;
    BoxDecoration boxDecoration = BoxDecoration(
      color: backgroundColor,
      border: hasBorder
          ? Border(
              top: borderTop ??
                  (showBorder[0] == true ? showBorderSide : BorderSide.none),
              right: borderRight ??
                  (showBorder[1] == true ? showBorderSide : BorderSide.none),
              bottom: borderBottom ??
                  (showBorder[2] == true ? showBorderSide : BorderSide.none),
              left: borderLeft ??
                  (showBorder[3] == true ? showBorderSide : BorderSide.none),
            )
          : null,
      borderRadius: hasBorderRadius > 0
          ? BorderRadius.only(
              topLeft: Radius.circular(
                  borderRadiusTopLeft ?? findTRBL(borderRadius)[0] ?? 0),
              topRight: Radius.circular(
                  borderRadiusTopRight ?? findTRBL(borderRadius)[1] ?? 0),
              bottomRight: Radius.circular(
                  borderRadiusBottomRight ?? findTRBL(borderRadius)[2] ?? 0),
              bottomLeft: Radius.circular(
                  borderRadiusBottomLeft ?? findTRBL(borderRadius)[3] ?? 0),
            )
          : null,
      boxShadow: boxShadow,
      gradient: gradient,
      image: backgroundImage != null
          ? DecorationImage(
              alignment: backgroundImageAlignment ?? Alignment.center,
              invertColors: backgroundImageInvertColors == true,
              opacity: backgroundImageOpacity ?? 1.0,
              image: (backgroundImage!.startsWith('http')
                  ? NetworkImage(backgroundImage!)
                  : AssetImage(backgroundImage!)) as ImageProvider,
              fit: backgroundImageFit ?? BoxFit.fill,
            )
          : null,
    );

    EdgeInsets showPadding = EdgeInsets.only(
      top: paddingTop ?? paddingVertical ?? findTRBL(padding)[0] ?? 0,
      right: paddingRight ?? paddingHorizontal ?? findTRBL(padding)[1] ?? 0,
      bottom: paddingBottom ?? paddingVertical ?? findTRBL(padding)[2] ?? 0,
      left: paddingLeft ?? paddingHorizontal ?? findTRBL(padding)[3] ?? 0,
    );
    EdgeInsets showMargin = EdgeInsets.only(
      top: marginTop ?? marginVertical ?? findTRBL(margin)[0] ?? 0,
      right: marginRight ?? marginHorizontal ?? findTRBL(margin)[1] ?? 0,
      bottom: marginBottom ?? marginVertical ?? findTRBL(margin)[2] ?? 0,
      left: marginLeft ?? marginHorizontal ?? findTRBL(margin)[3] ?? 0,
    );

    showChild = Container(
      width: width,
      height: height,
      padding: showPadding,
      margin: showMargin,
      decoration: boxDecoration,
      alignment: alignment,
      clipBehavior: Clip.none,
      child: showChild,
    );
    var useGlassFilter = glassFilter ?? 0;
    if (useGlassFilter > 10) useGlassFilter = 10;
    if (useGlassFilter > 0) {
      showChild = ClipRect(
        child: BackdropFilter(
            filter: ImageFilter.blur(
                sigmaX: useGlassFilter, sigmaY: useGlassFilter),
            child: showChild),
      );
    }

    if (onTap != null ||
        onPanUpdate != null ||
        onPanDown != null ||
        onPanEnd != null) {
      showChild = GestureDetector(
        onTap: onTap,
        onPanDown: onPanDown,
        onPanUpdate: onPanUpdate,
        onPanEnd: onPanEnd,
        child: showChild,
      );
    }
    if (flex != null) {
      showChild = Expanded(flex: flex!, child: showChild);
    }
    return showChild;
  }
}
